<!DOCTYPE html>

<html>
  <head>
    <meta charset="utf-8">
    
    <title>Writing your own ufunc &mdash; NumPy v1.18 Manual</title>
    
    <link rel="stylesheet" type="text/css" href="../_static/css/spc-bootstrap.css">
    <link rel="stylesheet" type="text/css" href="../_static/css/spc-extend.css">
    <link rel="stylesheet" href="../_static/scipy.css" type="text/css" >
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" >
    <link rel="stylesheet" href="../_static/graphviz.css" type="text/css" >
    
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '../',
        VERSION:     '1.18.1',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  false
      };
    </script>
    <script type="text/javascript" src="../_static/jquery.js"></script>
    <script type="text/javascript" src="../_static/underscore.js"></script>
    <script type="text/javascript" src="../_static/doctools.js"></script>
    <script type="text/javascript" src="../_static/language_data.js"></script>
    <script type="text/javascript" src="../_static/js/copybutton.js"></script>
    <link rel="author" title="About these documents" href="../about.html" >
    <link rel="index" title="Index" href="../genindex.html" >
    <link rel="search" title="Search" href="../search.html" >
    <link rel="top" title="NumPy v1.18 Manual" href="../index.html" >
    <link rel="up" title="Using NumPy C-API" href="c-info.html" >
    <link rel="next" title="Beyond the Basics" href="c-info.beyond-basics.html" >
    <link rel="prev" title="Using Python as glue" href="c-info.python-as-glue.html" > 
  </head>
  <body>
<div class="container">
  <div class="top-scipy-org-logo-header" style="background-color: #a2bae8;">
    <a href="../index.html">
      <img border=0 alt="NumPy" src="../_static/numpy_logo.png"></a>
    </div>
  </div>
</div>


    <div class="container">
      <div class="main">
        
	<div class="row-fluid">
	  <div class="span12">
	    <div class="spc-navbar">
              
    <ul class="nav nav-pills pull-left">
        <li class="active"><a href="https://numpy.org/">NumPy.org</a></li>
        <li class="active"><a href="https://numpy.org/doc">Docs</a></li>
        
        <li class="active"><a href="../index.html">NumPy v1.18 Manual</a></li>
        

          <li class="active"><a href="index.html" >NumPy User Guide</a></li>
          <li class="active"><a href="c-info.html" accesskey="U">Using NumPy C-API</a></li> 
    </ul>
              
              
    <ul class="nav nav-pills pull-right">
      <li class="active">
        <a href="../genindex.html" title="General Index"
           accesskey="I">index</a>
      </li>
      <li class="active">
        <a href="c-info.beyond-basics.html" title="Beyond the Basics"
           accesskey="N">next</a>
      </li>
      <li class="active">
        <a href="c-info.python-as-glue.html" title="Using Python as glue"
           accesskey="P">previous</a>
      </li>
    </ul>
              
	    </div>
	  </div>
	</div>
        

	<div class="row-fluid">
      <div class="spc-rightsidebar span3">
        <div class="sphinxsidebarwrapper">
  <h3><a href="../contents.html">Table of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">Writing your own ufunc</a><ul>
<li><a class="reference internal" href="#creating-a-new-universal-function">Creating a new universal function</a></li>
<li><a class="reference internal" href="#example-non-ufunc-extension">Example Non-ufunc extension</a></li>
<li><a class="reference internal" href="#example-numpy-ufunc-for-one-dtype">Example NumPy ufunc for one dtype</a></li>
<li><a class="reference internal" href="#example-numpy-ufunc-with-multiple-dtypes">Example NumPy ufunc with multiple dtypes</a></li>
<li><a class="reference internal" href="#example-numpy-ufunc-with-multiple-arguments-return-values">Example NumPy ufunc with multiple arguments/return values</a></li>
<li><a class="reference internal" href="#example-numpy-ufunc-with-structured-array-dtype-arguments">Example NumPy ufunc with structured array dtype arguments</a></li>
</ul>
</li>
</ul>

  <h4>Previous topic</h4>
  <p class="topless"><a href="c-info.python-as-glue.html"
                        title="previous chapter">Using Python as glue</a></p>
  <h4>Next topic</h4>
  <p class="topless"><a href="c-info.beyond-basics.html"
                        title="next chapter">Beyond the Basics</a></p>
<div id="searchbox" style="display: none" role="search">
  <h4>Quick search</h4>
    <div>
    <form class="search" action="../search.html" method="get">
      <input type="text" style="width: inherit;" name="q" />
      <input type="submit" value="search" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    </div>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
          <div class="span9">
            
        <div class="bodywrapper">
          <div class="body" id="spc-section-body">
            
  <div class="section" id="writing-your-own-ufunc">
<h1>Writing your own ufunc<a class="headerlink" href="#writing-your-own-ufunc" title="Permalink to this headline">¶</a></h1>
<div class="line-block">
<div class="line">I have the Power!</div>
<div class="line">— <em>He-Man</em></div>
</div>
<div class="section" id="creating-a-new-universal-function">
<span id="sec-creating-a-new"></span><h2>Creating a new universal function<a class="headerlink" href="#creating-a-new-universal-function" title="Permalink to this headline">¶</a></h2>
<p id="index-0">Before reading this, it may help to familiarize yourself with the basics
of C extensions for Python by reading/skimming the tutorials in Section 1
of <a class="reference external" href="https://docs.python.org/extending/index.html">Extending and Embedding the Python Interpreter</a> and in <a class="reference internal" href="c-info.how-to-extend.html"><span class="doc">How to extend
NumPy</span></a></p>
<p>The umath module is a computer-generated C-module that creates many
ufuncs. It provides a great many examples of how to create a universal
function. Creating your own ufunc that will make use of the ufunc
machinery is not difficult either. Suppose you have a function that
you want to operate element-by-element over its inputs. By creating a
new ufunc you will obtain a function that handles</p>
<ul class="simple">
<li><p>broadcasting</p></li>
<li><p>N-dimensional looping</p></li>
<li><p>automatic type-conversions with minimal memory usage</p></li>
<li><p>optional output arrays</p></li>
</ul>
<p>It is not difficult to create your own ufunc. All that is required is
a 1-d loop for each data-type you want to support. Each 1-d loop must
have a specific signature, and only ufuncs for fixed-size data-types
can be used. The function call used to create a new ufunc to work on
built-in data-types is given below. A different mechanism is used to
register ufuncs for user-defined data-types.</p>
<p>In the next several sections we give example code that can be
easily modified to create your own ufuncs. The examples are
successively more complete or complicated versions of the logit
function, a common function in statistical modeling. Logit is also
interesting because, due to the magic of IEEE standards (specifically
IEEE 754), all of the logit functions created below
automatically have the following behavior.</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">logit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="go">-inf</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">logit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="go">inf</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">logit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="go">nan</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">logit</span><span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span>
<span class="go">nan</span>
</pre></div>
</div>
<p>This is wonderful because the function writer doesn’t have to
manually propagate infs or nans.</p>
</div>
<div class="section" id="example-non-ufunc-extension">
<span id="sec-non-numpy-example"></span><h2>Example Non-ufunc extension<a class="headerlink" href="#example-non-ufunc-extension" title="Permalink to this headline">¶</a></h2>
<p id="index-1">For comparison and general edification of the reader we provide
a simple implementation of a C extension of logit that uses no
numpy.</p>
<p>To do this we need two files. The first is the C file which contains
the actual code, and the second is the setup.py file used to create
the module.</p>
<blockquote>
<div><div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf">&lt;Python.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;math.h&gt;</span><span class="cp"></span>

<span class="cm">/*</span>
<span class="cm"> * spammodule.c</span>
<span class="cm"> * This is the C code for a non-numpy Python extension to</span>
<span class="cm"> * define the logit function, where logit(p) = log(p/(1-p)).</span>
<span class="cm"> * This function will not work on numpy arrays automatically.</span>
<span class="cm"> * numpy.vectorize must be called in python to generate</span>
<span class="cm"> * a numpy-friendly function.</span>
<span class="cm"> *</span>
<span class="cm"> * Details explaining the Python-C API can be found under</span>
<span class="cm"> * &#39;Extending and Embedding&#39; and &#39;Python/C API&#39; at</span>
<span class="cm"> * docs.python.org .</span>
<span class="cm"> */</span>


<span class="cm">/* This declares the logit function */</span>
<span class="k">static</span> <span class="n">PyObject</span><span class="o">*</span> <span class="nf">spam_logit</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="n">self</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">args</span><span class="p">);</span>


<span class="cm">/*</span>
<span class="cm"> * This tells Python what methods this module has.</span>
<span class="cm"> * See the Python-C API for more information.</span>
<span class="cm"> */</span>
<span class="k">static</span> <span class="n">PyMethodDef</span> <span class="n">SpamMethods</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
    <span class="p">{</span><span class="s">&quot;logit&quot;</span><span class="p">,</span>
        <span class="n">spam_logit</span><span class="p">,</span>
        <span class="n">METH_VARARGS</span><span class="p">,</span> <span class="s">&quot;compute logit&quot;</span><span class="p">},</span>
    <span class="p">{</span><span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">}</span>
<span class="p">};</span>


<span class="cm">/*</span>
<span class="cm"> * This actually defines the logit function for</span>
<span class="cm"> * input args from Python.</span>
<span class="cm"> */</span>

<span class="k">static</span> <span class="n">PyObject</span><span class="o">*</span> <span class="nf">spam_logit</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="n">self</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">double</span> <span class="n">p</span><span class="p">;</span>

    <span class="cm">/* This parses the Python argument into a double */</span>
    <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">PyArg_ParseTuple</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="s">&quot;d&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">p</span><span class="p">))</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="cm">/* THE ACTUAL LOGIT FUNCTION */</span>
    <span class="n">p</span> <span class="o">=</span> <span class="n">p</span><span class="o">/</span><span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="n">p</span><span class="p">);</span>
    <span class="n">p</span> <span class="o">=</span> <span class="n">log</span><span class="p">(</span><span class="n">p</span><span class="p">);</span>

    <span class="cm">/*This builds the answer back into a python object */</span>
    <span class="k">return</span> <span class="n">Py_BuildValue</span><span class="p">(</span><span class="s">&quot;d&quot;</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
<span class="p">}</span>


<span class="cm">/* This initiates the module using the above definitions. */</span>
<span class="cp">#if PY_VERSION_HEX &gt;= 0x03000000</span>
<span class="k">static</span> <span class="k">struct</span> <span class="n">PyModuleDef</span> <span class="n">moduledef</span> <span class="o">=</span> <span class="p">{</span>
    <span class="n">PyModuleDef_HEAD_INIT</span><span class="p">,</span>
    <span class="s">&quot;spam&quot;</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="o">-</span><span class="mi">1</span><span class="p">,</span>
    <span class="n">SpamMethods</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="nb">NULL</span>
<span class="p">};</span>

<span class="n">PyMODINIT_FUNC</span> <span class="nf">PyInit_spam</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">m</span><span class="p">;</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">PyModule_Create</span><span class="p">(</span><span class="o">&amp;</span><span class="n">moduledef</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">m</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="n">m</span><span class="p">;</span>
<span class="p">}</span>
<span class="cp">#else</span>
<span class="n">PyMODINIT_FUNC</span> <span class="nf">initspam</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">m</span><span class="p">;</span>

    <span class="n">m</span> <span class="o">=</span> <span class="n">Py_InitModule</span><span class="p">(</span><span class="s">&quot;spam&quot;</span><span class="p">,</span> <span class="n">SpamMethods</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">m</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
<span class="cp">#endif</span>
</pre></div>
</div>
</div></blockquote>
<p>To use the setup.py file, place setup.py and spammodule.c in the same
folder. Then python setup.py build will build the module to import,
or setup.py install will install the module to your site-packages
directory.</p>
<blockquote>
<div><div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="sd">&#39;&#39;&#39;</span>
<span class="sd">    setup.py file for spammodule.c</span>

<span class="sd">    Calling</span>
<span class="sd">    $python setup.py build_ext --inplace</span>
<span class="sd">    will build the extension library in the current file.</span>

<span class="sd">    Calling</span>
<span class="sd">    $python setup.py build</span>
<span class="sd">    will build a file that looks like ./build/lib*, where</span>
<span class="sd">    lib* is a file that begins with lib. The library will</span>
<span class="sd">    be in this file and end with a C library extension,</span>
<span class="sd">    such as .so</span>

<span class="sd">    Calling</span>
<span class="sd">    $python setup.py install</span>
<span class="sd">    will install the module in your site-packages file.</span>

<span class="sd">    See the distutils section of</span>
<span class="sd">    &#39;Extending and Embedding the Python Interpreter&#39;</span>
<span class="sd">    at docs.python.org for more information.</span>
<span class="sd">&#39;&#39;&#39;</span>


<span class="kn">from</span> <span class="nn">distutils.core</span> <span class="kn">import</span> <span class="n">setup</span><span class="p">,</span> <span class="n">Extension</span>

<span class="n">module1</span> <span class="o">=</span> <span class="n">Extension</span><span class="p">(</span><span class="s1">&#39;spam&#39;</span><span class="p">,</span> <span class="n">sources</span><span class="o">=</span><span class="p">[</span><span class="s1">&#39;spammodule.c&#39;</span><span class="p">],</span>
                        <span class="n">include_dirs</span><span class="o">=</span><span class="p">[</span><span class="s1">&#39;/usr/local/lib&#39;</span><span class="p">])</span>

<span class="n">setup</span><span class="p">(</span><span class="n">name</span> <span class="o">=</span> <span class="s1">&#39;spam&#39;</span><span class="p">,</span>
        <span class="n">version</span><span class="o">=</span><span class="s1">&#39;1.0&#39;</span><span class="p">,</span>
        <span class="n">description</span><span class="o">=</span><span class="s1">&#39;This is my spam package&#39;</span><span class="p">,</span>
        <span class="n">ext_modules</span> <span class="o">=</span> <span class="p">[</span><span class="n">module1</span><span class="p">])</span>
</pre></div>
</div>
</div></blockquote>
<p>Once the spam module is imported into python, you can call logit
via spam.logit. Note that the function used above cannot be applied
as-is to numpy arrays. To do so we must call numpy.vectorize on it.
For example, if a python interpreter is opened in the file containing
the spam library or spam has been installed, one can perform the
following commands:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">spam</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">spam</span><span class="o">.</span><span class="n">logit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="go">-inf</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">spam</span><span class="o">.</span><span class="n">logit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="go">inf</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">spam</span><span class="o">.</span><span class="n">logit</span><span class="p">(</span><span class="mf">0.5</span><span class="p">)</span>
<span class="go">0.0</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">x</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">10</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">spam</span><span class="o">.</span><span class="n">logit</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="go">TypeError: only length-1 arrays can be converted to Python scalars</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">f</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">vectorize</span><span class="p">(</span><span class="n">spam</span><span class="o">.</span><span class="n">logit</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">f</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="go">array([       -inf, -2.07944154, -1.25276297, -0.69314718, -0.22314355,</span>
<span class="go">    0.22314355,  0.69314718,  1.25276297,  2.07944154,         inf])</span>
</pre></div>
</div>
<p>THE RESULTING LOGIT FUNCTION IS NOT FAST! numpy.vectorize simply
loops over spam.logit. The loop is done at the C level, but the numpy
array is constantly being parsed and build back up. This is expensive.
When the author compared numpy.vectorize(spam.logit) against the
logit ufuncs constructed below, the logit ufuncs were almost exactly
4 times faster. Larger or smaller speedups are, of course, possible
depending on the nature of the function.</p>
</div>
<div class="section" id="example-numpy-ufunc-for-one-dtype">
<span id="sec-numpy-one-loop"></span><h2>Example NumPy ufunc for one dtype<a class="headerlink" href="#example-numpy-ufunc-for-one-dtype" title="Permalink to this headline">¶</a></h2>
<p id="index-2">For simplicity we give a ufunc for a single dtype, the ‘f8’ double.
As in the previous section, we first give the .c file and then the
setup.py file used to create the module containing the ufunc.</p>
<p>The place in the code corresponding to the actual computations for
the ufunc are marked with /*BEGIN main ufunc computation*/ and
/*END main ufunc computation*/. The code in between those lines is
the primary thing that must be changed to create your own ufunc.</p>
<blockquote>
<div><div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf">&quot;Python.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;math.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;numpy/ndarraytypes.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;numpy/ufuncobject.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;numpy/npy_3kcompat.h&quot;</span><span class="cp"></span>

<span class="cm">/*</span>
<span class="cm"> * single_type_logit.c</span>
<span class="cm"> * This is the C code for creating your own</span>
<span class="cm"> * NumPy ufunc for a logit function.</span>
<span class="cm"> *</span>
<span class="cm"> * In this code we only define the ufunc for</span>
<span class="cm"> * a single dtype. The computations that must</span>
<span class="cm"> * be replaced to create a ufunc for</span>
<span class="cm"> * a different function are marked with BEGIN</span>
<span class="cm"> * and END.</span>
<span class="cm"> *</span>
<span class="cm"> * Details explaining the Python-C API can be found under</span>
<span class="cm"> * &#39;Extending and Embedding&#39; and &#39;Python/C API&#39; at</span>
<span class="cm"> * docs.python.org .</span>
<span class="cm"> */</span>

<span class="k">static</span> <span class="n">PyMethodDef</span> <span class="n">LogitMethods</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
        <span class="p">{</span><span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">}</span>
<span class="p">};</span>

<span class="cm">/* The loop definition must precede the PyMODINIT_FUNC. */</span>

<span class="k">static</span> <span class="kt">void</span> <span class="nf">double_logit</span><span class="p">(</span><span class="kt">char</span> <span class="o">**</span><span class="n">args</span><span class="p">,</span> <span class="n">npy_intp</span> <span class="o">*</span><span class="n">dimensions</span><span class="p">,</span>
                            <span class="n">npy_intp</span><span class="o">*</span> <span class="n">steps</span><span class="p">,</span> <span class="kt">void</span><span class="o">*</span> <span class="n">data</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">npy_intp</span> <span class="n">i</span><span class="p">;</span>
    <span class="n">npy_intp</span> <span class="n">n</span> <span class="o">=</span> <span class="n">dimensions</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">in</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="o">*</span><span class="n">out</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
    <span class="n">npy_intp</span> <span class="n">in_step</span> <span class="o">=</span> <span class="n">steps</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">out_step</span> <span class="o">=</span> <span class="n">steps</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>

    <span class="kt">double</span> <span class="n">tmp</span><span class="p">;</span>

    <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="cm">/*BEGIN main ufunc computation*/</span>
        <span class="n">tmp</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">double</span> <span class="o">*</span><span class="p">)</span><span class="n">in</span><span class="p">;</span>
        <span class="n">tmp</span> <span class="o">/=</span> <span class="mi">1</span><span class="o">-</span><span class="n">tmp</span><span class="p">;</span>
        <span class="o">*</span><span class="p">((</span><span class="kt">double</span> <span class="o">*</span><span class="p">)</span><span class="n">out</span><span class="p">)</span> <span class="o">=</span> <span class="n">log</span><span class="p">(</span><span class="n">tmp</span><span class="p">);</span>
        <span class="cm">/*END main ufunc computation*/</span>

        <span class="n">in</span> <span class="o">+=</span> <span class="n">in_step</span><span class="p">;</span>
        <span class="n">out</span> <span class="o">+=</span> <span class="n">out_step</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="cm">/*This a pointer to the above function*/</span>
<span class="n">PyUFuncGenericFunction</span> <span class="n">funcs</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="o">&amp;</span><span class="n">double_logit</span><span class="p">};</span>

<span class="cm">/* These are the input and return dtypes of logit.*/</span>
<span class="k">static</span> <span class="kt">char</span> <span class="n">types</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">NPY_DOUBLE</span><span class="p">,</span> <span class="n">NPY_DOUBLE</span><span class="p">};</span>

<span class="k">static</span> <span class="kt">void</span> <span class="o">*</span><span class="n">data</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="nb">NULL</span><span class="p">};</span>

<span class="cp">#if PY_VERSION_HEX &gt;= 0x03000000</span>
<span class="k">static</span> <span class="k">struct</span> <span class="n">PyModuleDef</span> <span class="n">moduledef</span> <span class="o">=</span> <span class="p">{</span>
    <span class="n">PyModuleDef_HEAD_INIT</span><span class="p">,</span>
    <span class="s">&quot;npufunc&quot;</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="o">-</span><span class="mi">1</span><span class="p">,</span>
    <span class="n">LogitMethods</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="nb">NULL</span>
<span class="p">};</span>

<span class="n">PyMODINIT_FUNC</span> <span class="nf">PyInit_npufunc</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">m</span><span class="p">,</span> <span class="o">*</span><span class="n">logit</span><span class="p">,</span> <span class="o">*</span><span class="n">d</span><span class="p">;</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">PyModule_Create</span><span class="p">(</span><span class="o">&amp;</span><span class="n">moduledef</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">m</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">import_array</span><span class="p">();</span>
    <span class="n">import_umath</span><span class="p">();</span>

    <span class="n">logit</span> <span class="o">=</span> <span class="n">PyUFunc_FromFuncAndData</span><span class="p">(</span><span class="n">funcs</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">types</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span>
                                    <span class="n">PyUFunc_None</span><span class="p">,</span> <span class="s">&quot;logit&quot;</span><span class="p">,</span>
                                    <span class="s">&quot;logit_docstring&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

    <span class="n">d</span> <span class="o">=</span> <span class="n">PyModule_GetDict</span><span class="p">(</span><span class="n">m</span><span class="p">);</span>

    <span class="n">PyDict_SetItemString</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="s">&quot;logit&quot;</span><span class="p">,</span> <span class="n">logit</span><span class="p">);</span>
    <span class="n">Py_DECREF</span><span class="p">(</span><span class="n">logit</span><span class="p">);</span>

    <span class="k">return</span> <span class="n">m</span><span class="p">;</span>
<span class="p">}</span>
<span class="cp">#else</span>
<span class="n">PyMODINIT_FUNC</span> <span class="nf">initnpufunc</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">m</span><span class="p">,</span> <span class="o">*</span><span class="n">logit</span><span class="p">,</span> <span class="o">*</span><span class="n">d</span><span class="p">;</span>


    <span class="n">m</span> <span class="o">=</span> <span class="n">Py_InitModule</span><span class="p">(</span><span class="s">&quot;npufunc&quot;</span><span class="p">,</span> <span class="n">LogitMethods</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">m</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">import_array</span><span class="p">();</span>
    <span class="n">import_umath</span><span class="p">();</span>

    <span class="n">logit</span> <span class="o">=</span> <span class="n">PyUFunc_FromFuncAndData</span><span class="p">(</span><span class="n">funcs</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">types</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span>
                                    <span class="n">PyUFunc_None</span><span class="p">,</span> <span class="s">&quot;logit&quot;</span><span class="p">,</span>
                                    <span class="s">&quot;logit_docstring&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

    <span class="n">d</span> <span class="o">=</span> <span class="n">PyModule_GetDict</span><span class="p">(</span><span class="n">m</span><span class="p">);</span>

    <span class="n">PyDict_SetItemString</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="s">&quot;logit&quot;</span><span class="p">,</span> <span class="n">logit</span><span class="p">);</span>
    <span class="n">Py_DECREF</span><span class="p">(</span><span class="n">logit</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">#endif</span>
</pre></div>
</div>
</div></blockquote>
<p>This is a setup.py file for the above code. As before, the module
can be build via calling python setup.py build at the command prompt,
or installed to site-packages via python setup.py install.</p>
<blockquote>
<div><div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="sd">&#39;&#39;&#39;</span>
<span class="sd">    setup.py file for logit.c</span>
<span class="sd">    Note that since this is a numpy extension</span>
<span class="sd">    we use numpy.distutils instead of</span>
<span class="sd">    distutils from the python standard library.</span>

<span class="sd">    Calling</span>
<span class="sd">    $python setup.py build_ext --inplace</span>
<span class="sd">    will build the extension library in the current file.</span>

<span class="sd">    Calling</span>
<span class="sd">    $python setup.py build</span>
<span class="sd">    will build a file that looks like ./build/lib*, where</span>
<span class="sd">    lib* is a file that begins with lib. The library will</span>
<span class="sd">    be in this file and end with a C library extension,</span>
<span class="sd">    such as .so</span>

<span class="sd">    Calling</span>
<span class="sd">    $python setup.py install</span>
<span class="sd">    will install the module in your site-packages file.</span>

<span class="sd">    See the distutils section of</span>
<span class="sd">    &#39;Extending and Embedding the Python Interpreter&#39;</span>
<span class="sd">    at docs.python.org  and the documentation</span>
<span class="sd">    on numpy.distutils for more information.</span>
<span class="sd">&#39;&#39;&#39;</span>


<span class="k">def</span> <span class="nf">configuration</span><span class="p">(</span><span class="n">parent_package</span><span class="o">=</span><span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="n">top_path</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
    <span class="kn">import</span> <span class="nn">numpy</span>
    <span class="kn">from</span> <span class="nn">numpy.distutils.misc_util</span> <span class="kn">import</span> <span class="n">Configuration</span>

    <span class="n">config</span> <span class="o">=</span> <span class="n">Configuration</span><span class="p">(</span><span class="s1">&#39;npufunc_directory&#39;</span><span class="p">,</span>
                           <span class="n">parent_package</span><span class="p">,</span>
                           <span class="n">top_path</span><span class="p">)</span>
    <span class="n">config</span><span class="o">.</span><span class="n">add_extension</span><span class="p">(</span><span class="s1">&#39;npufunc&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;single_type_logit.c&#39;</span><span class="p">])</span>

    <span class="k">return</span> <span class="n">config</span>

<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
    <span class="kn">from</span> <span class="nn">numpy.distutils.core</span> <span class="kn">import</span> <span class="n">setup</span>
    <span class="n">setup</span><span class="p">(</span><span class="n">configuration</span><span class="o">=</span><span class="n">configuration</span><span class="p">)</span>
</pre></div>
</div>
</div></blockquote>
<p>After the above has been installed, it can be imported and used as follows.</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">npufunc</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">npufunc</span><span class="o">.</span><span class="n">logit</span><span class="p">(</span><span class="mf">0.5</span><span class="p">)</span>
<span class="go">0.0</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">npufunc</span><span class="o">.</span><span class="n">logit</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="go">array([       -inf, -1.09861229,  0.        ,  1.09861229,         inf])</span>
</pre></div>
</div>
</div>
<div class="section" id="example-numpy-ufunc-with-multiple-dtypes">
<span id="sec-numpy-many-loop"></span><h2>Example NumPy ufunc with multiple dtypes<a class="headerlink" href="#example-numpy-ufunc-with-multiple-dtypes" title="Permalink to this headline">¶</a></h2>
<p id="index-3">We finally give an example of a full ufunc, with inner loops for
half-floats, floats, doubles, and long doubles. As in the previous
sections we first give the .c file and then the corresponding
setup.py file.</p>
<p>The places in the code corresponding to the actual computations for
the ufunc are marked with /*BEGIN main ufunc computation*/ and
/*END main ufunc computation*/. The code in between those lines is
the primary thing that must be changed to create your own ufunc.</p>
<blockquote>
<div><div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf">&quot;Python.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;math.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;numpy/ndarraytypes.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;numpy/ufuncobject.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;numpy/halffloat.h&quot;</span><span class="cp"></span>

<span class="cm">/*</span>
<span class="cm"> * multi_type_logit.c</span>
<span class="cm"> * This is the C code for creating your own</span>
<span class="cm"> * NumPy ufunc for a logit function.</span>
<span class="cm"> *</span>
<span class="cm"> * Each function of the form type_logit defines the</span>
<span class="cm"> * logit function for a different numpy dtype. Each</span>
<span class="cm"> * of these functions must be modified when you</span>
<span class="cm"> * create your own ufunc. The computations that must</span>
<span class="cm"> * be replaced to create a ufunc for</span>
<span class="cm"> * a different function are marked with BEGIN</span>
<span class="cm"> * and END.</span>
<span class="cm"> *</span>
<span class="cm"> * Details explaining the Python-C API can be found under</span>
<span class="cm"> * &#39;Extending and Embedding&#39; and &#39;Python/C API&#39; at</span>
<span class="cm"> * docs.python.org .</span>
<span class="cm"> *</span>
<span class="cm"> */</span>


<span class="k">static</span> <span class="n">PyMethodDef</span> <span class="n">LogitMethods</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
        <span class="p">{</span><span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">}</span>
<span class="p">};</span>

<span class="cm">/* The loop definitions must precede the PyMODINIT_FUNC. */</span>

<span class="k">static</span> <span class="kt">void</span> <span class="nf">long_double_logit</span><span class="p">(</span><span class="kt">char</span> <span class="o">**</span><span class="n">args</span><span class="p">,</span> <span class="n">npy_intp</span> <span class="o">*</span><span class="n">dimensions</span><span class="p">,</span>
                              <span class="n">npy_intp</span><span class="o">*</span> <span class="n">steps</span><span class="p">,</span> <span class="kt">void</span><span class="o">*</span> <span class="n">data</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">npy_intp</span> <span class="n">i</span><span class="p">;</span>
    <span class="n">npy_intp</span> <span class="n">n</span> <span class="o">=</span> <span class="n">dimensions</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">in</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="o">*</span><span class="n">out</span><span class="o">=</span><span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
    <span class="n">npy_intp</span> <span class="n">in_step</span> <span class="o">=</span> <span class="n">steps</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">out_step</span> <span class="o">=</span> <span class="n">steps</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>

    <span class="kt">long</span> <span class="kt">double</span> <span class="n">tmp</span><span class="p">;</span>

    <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="cm">/*BEGIN main ufunc computation*/</span>
        <span class="n">tmp</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">long</span> <span class="kt">double</span> <span class="o">*</span><span class="p">)</span><span class="n">in</span><span class="p">;</span>
        <span class="n">tmp</span> <span class="o">/=</span> <span class="mi">1</span><span class="o">-</span><span class="n">tmp</span><span class="p">;</span>
        <span class="o">*</span><span class="p">((</span><span class="kt">long</span> <span class="kt">double</span> <span class="o">*</span><span class="p">)</span><span class="n">out</span><span class="p">)</span> <span class="o">=</span> <span class="n">logl</span><span class="p">(</span><span class="n">tmp</span><span class="p">);</span>
        <span class="cm">/*END main ufunc computation*/</span>

        <span class="n">in</span> <span class="o">+=</span> <span class="n">in_step</span><span class="p">;</span>
        <span class="n">out</span> <span class="o">+=</span> <span class="n">out_step</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="k">static</span> <span class="kt">void</span> <span class="nf">double_logit</span><span class="p">(</span><span class="kt">char</span> <span class="o">**</span><span class="n">args</span><span class="p">,</span> <span class="n">npy_intp</span> <span class="o">*</span><span class="n">dimensions</span><span class="p">,</span>
                         <span class="n">npy_intp</span><span class="o">*</span> <span class="n">steps</span><span class="p">,</span> <span class="kt">void</span><span class="o">*</span> <span class="n">data</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">npy_intp</span> <span class="n">i</span><span class="p">;</span>
    <span class="n">npy_intp</span> <span class="n">n</span> <span class="o">=</span> <span class="n">dimensions</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">in</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="o">*</span><span class="n">out</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
    <span class="n">npy_intp</span> <span class="n">in_step</span> <span class="o">=</span> <span class="n">steps</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">out_step</span> <span class="o">=</span> <span class="n">steps</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>

    <span class="kt">double</span> <span class="n">tmp</span><span class="p">;</span>

    <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="cm">/*BEGIN main ufunc computation*/</span>
        <span class="n">tmp</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">double</span> <span class="o">*</span><span class="p">)</span><span class="n">in</span><span class="p">;</span>
        <span class="n">tmp</span> <span class="o">/=</span> <span class="mi">1</span><span class="o">-</span><span class="n">tmp</span><span class="p">;</span>
        <span class="o">*</span><span class="p">((</span><span class="kt">double</span> <span class="o">*</span><span class="p">)</span><span class="n">out</span><span class="p">)</span> <span class="o">=</span> <span class="n">log</span><span class="p">(</span><span class="n">tmp</span><span class="p">);</span>
        <span class="cm">/*END main ufunc computation*/</span>

        <span class="n">in</span> <span class="o">+=</span> <span class="n">in_step</span><span class="p">;</span>
        <span class="n">out</span> <span class="o">+=</span> <span class="n">out_step</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="k">static</span> <span class="kt">void</span> <span class="nf">float_logit</span><span class="p">(</span><span class="kt">char</span> <span class="o">**</span><span class="n">args</span><span class="p">,</span> <span class="n">npy_intp</span> <span class="o">*</span><span class="n">dimensions</span><span class="p">,</span>
                        <span class="n">npy_intp</span><span class="o">*</span> <span class="n">steps</span><span class="p">,</span> <span class="kt">void</span><span class="o">*</span> <span class="n">data</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">npy_intp</span> <span class="n">i</span><span class="p">;</span>
    <span class="n">npy_intp</span> <span class="n">n</span> <span class="o">=</span> <span class="n">dimensions</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">in</span><span class="o">=</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="o">*</span><span class="n">out</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
    <span class="n">npy_intp</span> <span class="n">in_step</span> <span class="o">=</span> <span class="n">steps</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">out_step</span> <span class="o">=</span> <span class="n">steps</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>

    <span class="kt">float</span> <span class="n">tmp</span><span class="p">;</span>

    <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="cm">/*BEGIN main ufunc computation*/</span>
        <span class="n">tmp</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">float</span> <span class="o">*</span><span class="p">)</span><span class="n">in</span><span class="p">;</span>
        <span class="n">tmp</span> <span class="o">/=</span> <span class="mi">1</span><span class="o">-</span><span class="n">tmp</span><span class="p">;</span>
        <span class="o">*</span><span class="p">((</span><span class="kt">float</span> <span class="o">*</span><span class="p">)</span><span class="n">out</span><span class="p">)</span> <span class="o">=</span> <span class="n">logf</span><span class="p">(</span><span class="n">tmp</span><span class="p">);</span>
        <span class="cm">/*END main ufunc computation*/</span>

        <span class="n">in</span> <span class="o">+=</span> <span class="n">in_step</span><span class="p">;</span>
        <span class="n">out</span> <span class="o">+=</span> <span class="n">out_step</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>


<span class="k">static</span> <span class="kt">void</span> <span class="nf">half_float_logit</span><span class="p">(</span><span class="kt">char</span> <span class="o">**</span><span class="n">args</span><span class="p">,</span> <span class="n">npy_intp</span> <span class="o">*</span><span class="n">dimensions</span><span class="p">,</span>
                             <span class="n">npy_intp</span><span class="o">*</span> <span class="n">steps</span><span class="p">,</span> <span class="kt">void</span><span class="o">*</span> <span class="n">data</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">npy_intp</span> <span class="n">i</span><span class="p">;</span>
    <span class="n">npy_intp</span> <span class="n">n</span> <span class="o">=</span> <span class="n">dimensions</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">in</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="o">*</span><span class="n">out</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
    <span class="n">npy_intp</span> <span class="n">in_step</span> <span class="o">=</span> <span class="n">steps</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">out_step</span> <span class="o">=</span> <span class="n">steps</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>

    <span class="kt">float</span> <span class="n">tmp</span><span class="p">;</span>

    <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>

        <span class="cm">/*BEGIN main ufunc computation*/</span>
        <span class="n">tmp</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">npy_half</span> <span class="o">*</span><span class="p">)</span><span class="n">in</span><span class="p">;</span>
        <span class="n">tmp</span> <span class="o">=</span> <span class="n">npy_half_to_float</span><span class="p">(</span><span class="n">tmp</span><span class="p">);</span>
        <span class="n">tmp</span> <span class="o">/=</span> <span class="mi">1</span><span class="o">-</span><span class="n">tmp</span><span class="p">;</span>
        <span class="n">tmp</span> <span class="o">=</span> <span class="n">logf</span><span class="p">(</span><span class="n">tmp</span><span class="p">);</span>
        <span class="o">*</span><span class="p">((</span><span class="n">npy_half</span> <span class="o">*</span><span class="p">)</span><span class="n">out</span><span class="p">)</span> <span class="o">=</span> <span class="n">npy_float_to_half</span><span class="p">(</span><span class="n">tmp</span><span class="p">);</span>
        <span class="cm">/*END main ufunc computation*/</span>

        <span class="n">in</span> <span class="o">+=</span> <span class="n">in_step</span><span class="p">;</span>
        <span class="n">out</span> <span class="o">+=</span> <span class="n">out_step</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>


<span class="cm">/*This gives pointers to the above functions*/</span>
<span class="n">PyUFuncGenericFunction</span> <span class="n">funcs</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="o">&amp;</span><span class="n">half_float_logit</span><span class="p">,</span>
                                   <span class="o">&amp;</span><span class="n">float_logit</span><span class="p">,</span>
                                   <span class="o">&amp;</span><span class="n">double_logit</span><span class="p">,</span>
                                   <span class="o">&amp;</span><span class="n">long_double_logit</span><span class="p">};</span>

<span class="k">static</span> <span class="kt">char</span> <span class="n">types</span><span class="p">[</span><span class="mi">8</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">NPY_HALF</span><span class="p">,</span> <span class="n">NPY_HALF</span><span class="p">,</span>
                <span class="n">NPY_FLOAT</span><span class="p">,</span> <span class="n">NPY_FLOAT</span><span class="p">,</span>
                <span class="n">NPY_DOUBLE</span><span class="p">,</span><span class="n">NPY_DOUBLE</span><span class="p">,</span>
                <span class="n">NPY_LONGDOUBLE</span><span class="p">,</span> <span class="n">NPY_LONGDOUBLE</span><span class="p">};</span>
<span class="k">static</span> <span class="kt">void</span> <span class="o">*</span><span class="n">data</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">};</span>

<span class="cp">#if PY_VERSION_HEX &gt;= 0x03000000</span>
<span class="k">static</span> <span class="k">struct</span> <span class="n">PyModuleDef</span> <span class="n">moduledef</span> <span class="o">=</span> <span class="p">{</span>
    <span class="n">PyModuleDef_HEAD_INIT</span><span class="p">,</span>
    <span class="s">&quot;npufunc&quot;</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="o">-</span><span class="mi">1</span><span class="p">,</span>
    <span class="n">LogitMethods</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="nb">NULL</span>
<span class="p">};</span>

<span class="n">PyMODINIT_FUNC</span> <span class="nf">PyInit_npufunc</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">m</span><span class="p">,</span> <span class="o">*</span><span class="n">logit</span><span class="p">,</span> <span class="o">*</span><span class="n">d</span><span class="p">;</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">PyModule_Create</span><span class="p">(</span><span class="o">&amp;</span><span class="n">moduledef</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">m</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">import_array</span><span class="p">();</span>
    <span class="n">import_umath</span><span class="p">();</span>

    <span class="n">logit</span> <span class="o">=</span> <span class="n">PyUFunc_FromFuncAndData</span><span class="p">(</span><span class="n">funcs</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">types</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span>
                                    <span class="n">PyUFunc_None</span><span class="p">,</span> <span class="s">&quot;logit&quot;</span><span class="p">,</span>
                                    <span class="s">&quot;logit_docstring&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

    <span class="n">d</span> <span class="o">=</span> <span class="n">PyModule_GetDict</span><span class="p">(</span><span class="n">m</span><span class="p">);</span>

    <span class="n">PyDict_SetItemString</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="s">&quot;logit&quot;</span><span class="p">,</span> <span class="n">logit</span><span class="p">);</span>
    <span class="n">Py_DECREF</span><span class="p">(</span><span class="n">logit</span><span class="p">);</span>

    <span class="k">return</span> <span class="n">m</span><span class="p">;</span>
<span class="p">}</span>
<span class="cp">#else</span>
<span class="n">PyMODINIT_FUNC</span> <span class="nf">initnpufunc</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">m</span><span class="p">,</span> <span class="o">*</span><span class="n">logit</span><span class="p">,</span> <span class="o">*</span><span class="n">d</span><span class="p">;</span>


    <span class="n">m</span> <span class="o">=</span> <span class="n">Py_InitModule</span><span class="p">(</span><span class="s">&quot;npufunc&quot;</span><span class="p">,</span> <span class="n">LogitMethods</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">m</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">import_array</span><span class="p">();</span>
    <span class="n">import_umath</span><span class="p">();</span>

    <span class="n">logit</span> <span class="o">=</span> <span class="n">PyUFunc_FromFuncAndData</span><span class="p">(</span><span class="n">funcs</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">types</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span>
                                    <span class="n">PyUFunc_None</span><span class="p">,</span> <span class="s">&quot;logit&quot;</span><span class="p">,</span>
                                    <span class="s">&quot;logit_docstring&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

    <span class="n">d</span> <span class="o">=</span> <span class="n">PyModule_GetDict</span><span class="p">(</span><span class="n">m</span><span class="p">);</span>

    <span class="n">PyDict_SetItemString</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="s">&quot;logit&quot;</span><span class="p">,</span> <span class="n">logit</span><span class="p">);</span>
    <span class="n">Py_DECREF</span><span class="p">(</span><span class="n">logit</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">#endif</span>
</pre></div>
</div>
</div></blockquote>
<p>This is a setup.py file for the above code. As before, the module
can be build via calling python setup.py build at the command prompt,
or installed to site-packages via python setup.py install.</p>
<blockquote>
<div><div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="sd">&#39;&#39;&#39;</span>
<span class="sd">    setup.py file for logit.c</span>
<span class="sd">    Note that since this is a numpy extension</span>
<span class="sd">    we use numpy.distutils instead of</span>
<span class="sd">    distutils from the python standard library.</span>

<span class="sd">    Calling</span>
<span class="sd">    $python setup.py build_ext --inplace</span>
<span class="sd">    will build the extension library in the current file.</span>

<span class="sd">    Calling</span>
<span class="sd">    $python setup.py build</span>
<span class="sd">    will build a file that looks like ./build/lib*, where</span>
<span class="sd">    lib* is a file that begins with lib. The library will</span>
<span class="sd">    be in this file and end with a C library extension,</span>
<span class="sd">    such as .so</span>

<span class="sd">    Calling</span>
<span class="sd">    $python setup.py install</span>
<span class="sd">    will install the module in your site-packages file.</span>

<span class="sd">    See the distutils section of</span>
<span class="sd">    &#39;Extending and Embedding the Python Interpreter&#39;</span>
<span class="sd">    at docs.python.org  and the documentation</span>
<span class="sd">    on numpy.distutils for more information.</span>
<span class="sd">&#39;&#39;&#39;</span>


<span class="k">def</span> <span class="nf">configuration</span><span class="p">(</span><span class="n">parent_package</span><span class="o">=</span><span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="n">top_path</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
    <span class="kn">import</span> <span class="nn">numpy</span>
    <span class="kn">from</span> <span class="nn">numpy.distutils.misc_util</span> <span class="kn">import</span> <span class="n">Configuration</span>
    <span class="kn">from</span> <span class="nn">numpy.distutils.misc_util</span> <span class="kn">import</span> <span class="n">get_info</span>

    <span class="c1">#Necessary for the half-float d-type.</span>
    <span class="n">info</span> <span class="o">=</span> <span class="n">get_info</span><span class="p">(</span><span class="s1">&#39;npymath&#39;</span><span class="p">)</span>

    <span class="n">config</span> <span class="o">=</span> <span class="n">Configuration</span><span class="p">(</span><span class="s1">&#39;npufunc_directory&#39;</span><span class="p">,</span>
                            <span class="n">parent_package</span><span class="p">,</span>
                            <span class="n">top_path</span><span class="p">)</span>
    <span class="n">config</span><span class="o">.</span><span class="n">add_extension</span><span class="p">(</span><span class="s1">&#39;npufunc&#39;</span><span class="p">,</span>
                            <span class="p">[</span><span class="s1">&#39;multi_type_logit.c&#39;</span><span class="p">],</span>
                            <span class="n">extra_info</span><span class="o">=</span><span class="n">info</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">config</span>

<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
    <span class="kn">from</span> <span class="nn">numpy.distutils.core</span> <span class="kn">import</span> <span class="n">setup</span>
    <span class="n">setup</span><span class="p">(</span><span class="n">configuration</span><span class="o">=</span><span class="n">configuration</span><span class="p">)</span>
</pre></div>
</div>
</div></blockquote>
<p>After the above has been installed, it can be imported and used as follows.</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">npufunc</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">npufunc</span><span class="o">.</span><span class="n">logit</span><span class="p">(</span><span class="mf">0.5</span><span class="p">)</span>
<span class="go">0.0</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">npufunc</span><span class="o">.</span><span class="n">logit</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="go">array([       -inf, -1.09861229,  0.        ,  1.09861229,         inf])</span>
</pre></div>
</div>
</div>
<div class="section" id="example-numpy-ufunc-with-multiple-arguments-return-values">
<span id="sec-numpy-many-arg"></span><h2>Example NumPy ufunc with multiple arguments/return values<a class="headerlink" href="#example-numpy-ufunc-with-multiple-arguments-return-values" title="Permalink to this headline">¶</a></h2>
<p>Our final example is a ufunc with multiple arguments. It is a modification
of the code for a logit ufunc for data with a single dtype. We
compute (A*B, logit(A*B)).</p>
<p>We only give the C code as the setup.py file is exactly the same as
the setup.py file in <a class="reference internal" href="#example-numpy-ufunc-for-one-dtype">Example NumPy ufunc for one dtype</a>, except that
the line</p>
<blockquote>
<div><div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">config</span><span class="o">.</span><span class="n">add_extension</span><span class="p">(</span><span class="s1">&#39;npufunc&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;single_type_logit.c&#39;</span><span class="p">])</span>
</pre></div>
</div>
</div></blockquote>
<p>is replaced with</p>
<blockquote>
<div><div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">config</span><span class="o">.</span><span class="n">add_extension</span><span class="p">(</span><span class="s1">&#39;npufunc&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;multi_arg_logit.c&#39;</span><span class="p">])</span>
</pre></div>
</div>
</div></blockquote>
<p>The C file is given below. The ufunc generated takes two arguments A
and B. It returns a tuple whose first element is A*B and whose second
element is logit(A*B). Note that it automatically supports broadcasting,
as well as all other properties of a ufunc.</p>
<blockquote>
<div><div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf">&quot;Python.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;math.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;numpy/ndarraytypes.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;numpy/ufuncobject.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;numpy/halffloat.h&quot;</span><span class="cp"></span>

<span class="cm">/*</span>
<span class="cm"> * multi_arg_logit.c</span>
<span class="cm"> * This is the C code for creating your own</span>
<span class="cm"> * NumPy ufunc for a multiple argument, multiple</span>
<span class="cm"> * return value ufunc. The places where the</span>
<span class="cm"> * ufunc computation is carried out are marked</span>
<span class="cm"> * with comments.</span>
<span class="cm"> *</span>
<span class="cm"> * Details explaining the Python-C API can be found under</span>
<span class="cm"> * &#39;Extending and Embedding&#39; and &#39;Python/C API&#39; at</span>
<span class="cm"> * docs.python.org .</span>
<span class="cm"> *</span>
<span class="cm"> */</span>


<span class="k">static</span> <span class="n">PyMethodDef</span> <span class="n">LogitMethods</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
        <span class="p">{</span><span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">}</span>
<span class="p">};</span>

<span class="cm">/* The loop definition must precede the PyMODINIT_FUNC. */</span>

<span class="k">static</span> <span class="kt">void</span> <span class="nf">double_logitprod</span><span class="p">(</span><span class="kt">char</span> <span class="o">**</span><span class="n">args</span><span class="p">,</span> <span class="n">npy_intp</span> <span class="o">*</span><span class="n">dimensions</span><span class="p">,</span>
                            <span class="n">npy_intp</span><span class="o">*</span> <span class="n">steps</span><span class="p">,</span> <span class="kt">void</span><span class="o">*</span> <span class="n">data</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">npy_intp</span> <span class="n">i</span><span class="p">;</span>
    <span class="n">npy_intp</span> <span class="n">n</span> <span class="o">=</span> <span class="n">dimensions</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">in1</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="o">*</span><span class="n">in2</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">out1</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="o">*</span><span class="n">out2</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span>
    <span class="n">npy_intp</span> <span class="n">in1_step</span> <span class="o">=</span> <span class="n">steps</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">in2_step</span> <span class="o">=</span> <span class="n">steps</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
    <span class="n">npy_intp</span> <span class="n">out1_step</span> <span class="o">=</span> <span class="n">steps</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">out2_step</span> <span class="o">=</span> <span class="n">steps</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span>

    <span class="kt">double</span> <span class="n">tmp</span><span class="p">;</span>

    <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="cm">/*BEGIN main ufunc computation*/</span>
        <span class="n">tmp</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">double</span> <span class="o">*</span><span class="p">)</span><span class="n">in1</span><span class="p">;</span>
        <span class="n">tmp</span> <span class="o">*=</span> <span class="o">*</span><span class="p">(</span><span class="kt">double</span> <span class="o">*</span><span class="p">)</span><span class="n">in2</span><span class="p">;</span>
        <span class="o">*</span><span class="p">((</span><span class="kt">double</span> <span class="o">*</span><span class="p">)</span><span class="n">out1</span><span class="p">)</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span>
        <span class="o">*</span><span class="p">((</span><span class="kt">double</span> <span class="o">*</span><span class="p">)</span><span class="n">out2</span><span class="p">)</span> <span class="o">=</span> <span class="n">log</span><span class="p">(</span><span class="n">tmp</span><span class="o">/</span><span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="n">tmp</span><span class="p">));</span>
        <span class="cm">/*END main ufunc computation*/</span>

        <span class="n">in1</span> <span class="o">+=</span> <span class="n">in1_step</span><span class="p">;</span>
        <span class="n">in2</span> <span class="o">+=</span> <span class="n">in2_step</span><span class="p">;</span>
        <span class="n">out1</span> <span class="o">+=</span> <span class="n">out1_step</span><span class="p">;</span>
        <span class="n">out2</span> <span class="o">+=</span> <span class="n">out2_step</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>


<span class="cm">/*This a pointer to the above function*/</span>
<span class="n">PyUFuncGenericFunction</span> <span class="n">funcs</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="o">&amp;</span><span class="n">double_logitprod</span><span class="p">};</span>

<span class="cm">/* These are the input and return dtypes of logit.*/</span>

<span class="k">static</span> <span class="kt">char</span> <span class="n">types</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">NPY_DOUBLE</span><span class="p">,</span> <span class="n">NPY_DOUBLE</span><span class="p">,</span>
                        <span class="n">NPY_DOUBLE</span><span class="p">,</span> <span class="n">NPY_DOUBLE</span><span class="p">};</span>


<span class="k">static</span> <span class="kt">void</span> <span class="o">*</span><span class="n">data</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="nb">NULL</span><span class="p">};</span>

<span class="cp">#if PY_VERSION_HEX &gt;= 0x03000000</span>
<span class="k">static</span> <span class="k">struct</span> <span class="n">PyModuleDef</span> <span class="n">moduledef</span> <span class="o">=</span> <span class="p">{</span>
    <span class="n">PyModuleDef_HEAD_INIT</span><span class="p">,</span>
    <span class="s">&quot;npufunc&quot;</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="o">-</span><span class="mi">1</span><span class="p">,</span>
    <span class="n">LogitMethods</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="nb">NULL</span>
<span class="p">};</span>

<span class="n">PyMODINIT_FUNC</span> <span class="nf">PyInit_npufunc</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">m</span><span class="p">,</span> <span class="o">*</span><span class="n">logit</span><span class="p">,</span> <span class="o">*</span><span class="n">d</span><span class="p">;</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">PyModule_Create</span><span class="p">(</span><span class="o">&amp;</span><span class="n">moduledef</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">m</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">import_array</span><span class="p">();</span>
    <span class="n">import_umath</span><span class="p">();</span>

    <span class="n">logit</span> <span class="o">=</span> <span class="n">PyUFunc_FromFuncAndData</span><span class="p">(</span><span class="n">funcs</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">types</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span>
                                    <span class="n">PyUFunc_None</span><span class="p">,</span> <span class="s">&quot;logit&quot;</span><span class="p">,</span>
                                    <span class="s">&quot;logit_docstring&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

    <span class="n">d</span> <span class="o">=</span> <span class="n">PyModule_GetDict</span><span class="p">(</span><span class="n">m</span><span class="p">);</span>

    <span class="n">PyDict_SetItemString</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="s">&quot;logit&quot;</span><span class="p">,</span> <span class="n">logit</span><span class="p">);</span>
    <span class="n">Py_DECREF</span><span class="p">(</span><span class="n">logit</span><span class="p">);</span>

    <span class="k">return</span> <span class="n">m</span><span class="p">;</span>
<span class="p">}</span>
<span class="cp">#else</span>
<span class="n">PyMODINIT_FUNC</span> <span class="nf">initnpufunc</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">m</span><span class="p">,</span> <span class="o">*</span><span class="n">logit</span><span class="p">,</span> <span class="o">*</span><span class="n">d</span><span class="p">;</span>


    <span class="n">m</span> <span class="o">=</span> <span class="n">Py_InitModule</span><span class="p">(</span><span class="s">&quot;npufunc&quot;</span><span class="p">,</span> <span class="n">LogitMethods</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">m</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">import_array</span><span class="p">();</span>
    <span class="n">import_umath</span><span class="p">();</span>

    <span class="n">logit</span> <span class="o">=</span> <span class="n">PyUFunc_FromFuncAndData</span><span class="p">(</span><span class="n">funcs</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">types</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span>
                                    <span class="n">PyUFunc_None</span><span class="p">,</span> <span class="s">&quot;logit&quot;</span><span class="p">,</span>
                                    <span class="s">&quot;logit_docstring&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

    <span class="n">d</span> <span class="o">=</span> <span class="n">PyModule_GetDict</span><span class="p">(</span><span class="n">m</span><span class="p">);</span>

    <span class="n">PyDict_SetItemString</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="s">&quot;logit&quot;</span><span class="p">,</span> <span class="n">logit</span><span class="p">);</span>
    <span class="n">Py_DECREF</span><span class="p">(</span><span class="n">logit</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">#endif</span>
</pre></div>
</div>
</div></blockquote>
</div>
<div class="section" id="example-numpy-ufunc-with-structured-array-dtype-arguments">
<span id="sec-numpy-struct-dtype"></span><h2>Example NumPy ufunc with structured array dtype arguments<a class="headerlink" href="#example-numpy-ufunc-with-structured-array-dtype-arguments" title="Permalink to this headline">¶</a></h2>
<p>This example shows how to create a ufunc for a structured array dtype.
For the example we show a trivial ufunc for adding two arrays with dtype
‘u8,u8,u8’. The process is a bit different from the other examples since
a call to <a class="reference internal" href="../reference/c-api/ufunc.html#c.PyUFunc_FromFuncAndData" title="PyUFunc_FromFuncAndData"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyUFunc_FromFuncAndData</span></code></a> doesn’t fully register ufuncs for
custom dtypes and structured array dtypes. We need to also call
<a class="reference internal" href="../reference/c-api/ufunc.html#c.PyUFunc_RegisterLoopForDescr" title="PyUFunc_RegisterLoopForDescr"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyUFunc_RegisterLoopForDescr</span></code></a> to finish setting up the ufunc.</p>
<p>We only give the C code as the setup.py file is exactly the same as
the setup.py file in <a class="reference internal" href="#example-numpy-ufunc-for-one-dtype">Example NumPy ufunc for one dtype</a>, except that
the line</p>
<blockquote>
<div><div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">config</span><span class="o">.</span><span class="n">add_extension</span><span class="p">(</span><span class="s1">&#39;npufunc&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;single_type_logit.c&#39;</span><span class="p">])</span>
</pre></div>
</div>
</div></blockquote>
<p>is replaced with</p>
<blockquote>
<div><div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">config</span><span class="o">.</span><span class="n">add_extension</span><span class="p">(</span><span class="s1">&#39;npufunc&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;add_triplet.c&#39;</span><span class="p">])</span>
</pre></div>
</div>
</div></blockquote>
<p>The C file is given below.</p>
<blockquote>
<div><div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf">&quot;Python.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;math.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;numpy/ndarraytypes.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;numpy/ufuncobject.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;numpy/npy_3kcompat.h&quot;</span><span class="cp"></span>


<span class="cm">/*</span>
<span class="cm"> * add_triplet.c</span>
<span class="cm"> * This is the C code for creating your own</span>
<span class="cm"> * NumPy ufunc for a structured array dtype.</span>
<span class="cm"> *</span>
<span class="cm"> * Details explaining the Python-C API can be found under</span>
<span class="cm"> * &#39;Extending and Embedding&#39; and &#39;Python/C API&#39; at</span>
<span class="cm"> * docs.python.org .</span>
<span class="cm"> */</span>

<span class="k">static</span> <span class="n">PyMethodDef</span> <span class="n">StructUfuncTestMethods</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
    <span class="p">{</span><span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">}</span>
<span class="p">};</span>

<span class="cm">/* The loop definition must precede the PyMODINIT_FUNC. */</span>

<span class="k">static</span> <span class="kt">void</span> <span class="nf">add_uint64_triplet</span><span class="p">(</span><span class="kt">char</span> <span class="o">**</span><span class="n">args</span><span class="p">,</span> <span class="n">npy_intp</span> <span class="o">*</span><span class="n">dimensions</span><span class="p">,</span>
                            <span class="n">npy_intp</span><span class="o">*</span> <span class="n">steps</span><span class="p">,</span> <span class="kt">void</span><span class="o">*</span> <span class="n">data</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">npy_intp</span> <span class="n">i</span><span class="p">;</span>
    <span class="n">npy_intp</span> <span class="n">is1</span><span class="o">=</span><span class="n">steps</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
    <span class="n">npy_intp</span> <span class="n">is2</span><span class="o">=</span><span class="n">steps</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
    <span class="n">npy_intp</span> <span class="n">os</span><span class="o">=</span><span class="n">steps</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
    <span class="n">npy_intp</span> <span class="n">n</span><span class="o">=</span><span class="n">dimensions</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
    <span class="kt">uint64_t</span> <span class="o">*</span><span class="n">x</span><span class="p">,</span> <span class="o">*</span><span class="n">y</span><span class="p">,</span> <span class="o">*</span><span class="n">z</span><span class="p">;</span>

    <span class="kt">char</span> <span class="o">*</span><span class="n">i1</span><span class="o">=</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">i2</span><span class="o">=</span><span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">op</span><span class="o">=</span><span class="n">args</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>

    <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>

        <span class="n">x</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint64_t</span><span class="o">*</span><span class="p">)</span><span class="n">i1</span><span class="p">;</span>
        <span class="n">y</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint64_t</span><span class="o">*</span><span class="p">)</span><span class="n">i2</span><span class="p">;</span>
        <span class="n">z</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint64_t</span><span class="o">*</span><span class="p">)</span><span class="n">op</span><span class="p">;</span>

        <span class="n">z</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">y</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
        <span class="n">z</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">x</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">y</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
        <span class="n">z</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">x</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="n">y</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>

        <span class="n">i1</span> <span class="o">+=</span> <span class="n">is1</span><span class="p">;</span>
        <span class="n">i2</span> <span class="o">+=</span> <span class="n">is2</span><span class="p">;</span>
        <span class="n">op</span> <span class="o">+=</span> <span class="n">os</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="cm">/* This a pointer to the above function */</span>
<span class="n">PyUFuncGenericFunction</span> <span class="n">funcs</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="o">&amp;</span><span class="n">add_uint64_triplet</span><span class="p">};</span>

<span class="cm">/* These are the input and return dtypes of add_uint64_triplet. */</span>
<span class="k">static</span> <span class="kt">char</span> <span class="n">types</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">NPY_UINT64</span><span class="p">,</span> <span class="n">NPY_UINT64</span><span class="p">,</span> <span class="n">NPY_UINT64</span><span class="p">};</span>

<span class="k">static</span> <span class="kt">void</span> <span class="o">*</span><span class="n">data</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="nb">NULL</span><span class="p">};</span>

<span class="cp">#if defined(NPY_PY3K)</span>
<span class="k">static</span> <span class="k">struct</span> <span class="n">PyModuleDef</span> <span class="n">moduledef</span> <span class="o">=</span> <span class="p">{</span>
    <span class="n">PyModuleDef_HEAD_INIT</span><span class="p">,</span>
    <span class="s">&quot;struct_ufunc_test&quot;</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="o">-</span><span class="mi">1</span><span class="p">,</span>
    <span class="n">StructUfuncTestMethods</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="nb">NULL</span><span class="p">,</span>
    <span class="nb">NULL</span>
<span class="p">};</span>
<span class="cp">#endif</span>

<span class="cp">#if defined(NPY_PY3K)</span>
<span class="n">PyMODINIT_FUNC</span> <span class="nf">PyInit_struct_ufunc_test</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="cp">#else</span>
<span class="n">PyMODINIT_FUNC</span> <span class="n">initstruct_ufunc_test</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="cp">#endif</span>
<span class="p">{</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">m</span><span class="p">,</span> <span class="o">*</span><span class="n">add_triplet</span><span class="p">,</span> <span class="o">*</span><span class="n">d</span><span class="p">;</span>
    <span class="n">PyObject</span> <span class="o">*</span><span class="n">dtype_dict</span><span class="p">;</span>
    <span class="n">PyArray_Descr</span> <span class="o">*</span><span class="n">dtype</span><span class="p">;</span>
    <span class="n">PyArray_Descr</span> <span class="o">*</span><span class="n">dtypes</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span>

<span class="cp">#if defined(NPY_PY3K)</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">PyModule_Create</span><span class="p">(</span><span class="o">&amp;</span><span class="n">moduledef</span><span class="p">);</span>
<span class="cp">#else</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">Py_InitModule</span><span class="p">(</span><span class="s">&quot;struct_ufunc_test&quot;</span><span class="p">,</span> <span class="n">StructUfuncTestMethods</span><span class="p">);</span>
<span class="cp">#endif</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">m</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
<span class="cp">#if defined(NPY_PY3K)</span>
        <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="cp">#else</span>
        <span class="k">return</span><span class="p">;</span>
<span class="cp">#endif</span>
    <span class="p">}</span>

    <span class="n">import_array</span><span class="p">();</span>
    <span class="n">import_umath</span><span class="p">();</span>

    <span class="cm">/* Create a new ufunc object */</span>
    <span class="n">add_triplet</span> <span class="o">=</span> <span class="n">PyUFunc_FromFuncAndData</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span>
                                    <span class="n">PyUFunc_None</span><span class="p">,</span> <span class="s">&quot;add_triplet&quot;</span><span class="p">,</span>
                                    <span class="s">&quot;add_triplet_docstring&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

    <span class="n">dtype_dict</span> <span class="o">=</span> <span class="n">Py_BuildValue</span><span class="p">(</span><span class="s">&quot;[(s, s), (s, s), (s, s)]&quot;</span><span class="p">,</span>
        <span class="s">&quot;f0&quot;</span><span class="p">,</span> <span class="s">&quot;u8&quot;</span><span class="p">,</span> <span class="s">&quot;f1&quot;</span><span class="p">,</span> <span class="s">&quot;u8&quot;</span><span class="p">,</span> <span class="s">&quot;f2&quot;</span><span class="p">,</span> <span class="s">&quot;u8&quot;</span><span class="p">);</span>
    <span class="n">PyArray_DescrConverter</span><span class="p">(</span><span class="n">dtype_dict</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">dtype</span><span class="p">);</span>
    <span class="n">Py_DECREF</span><span class="p">(</span><span class="n">dtype_dict</span><span class="p">);</span>

    <span class="n">dtypes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">dtype</span><span class="p">;</span>
    <span class="n">dtypes</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">dtype</span><span class="p">;</span>
    <span class="n">dtypes</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">dtype</span><span class="p">;</span>

    <span class="cm">/* Register ufunc for structured dtype */</span>
    <span class="n">PyUFunc_RegisterLoopForDescr</span><span class="p">(</span><span class="n">add_triplet</span><span class="p">,</span>
                                <span class="n">dtype</span><span class="p">,</span>
                                <span class="o">&amp;</span><span class="n">add_uint64_triplet</span><span class="p">,</span>
                                <span class="n">dtypes</span><span class="p">,</span>
                                <span class="nb">NULL</span><span class="p">);</span>

    <span class="n">d</span> <span class="o">=</span> <span class="n">PyModule_GetDict</span><span class="p">(</span><span class="n">m</span><span class="p">);</span>

    <span class="n">PyDict_SetItemString</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="s">&quot;add_triplet&quot;</span><span class="p">,</span> <span class="n">add_triplet</span><span class="p">);</span>
    <span class="n">Py_DECREF</span><span class="p">(</span><span class="n">add_triplet</span><span class="p">);</span>
<span class="cp">#if defined(NPY_PY3K)</span>
    <span class="k">return</span> <span class="n">m</span><span class="p">;</span>
<span class="cp">#endif</span>
<span class="p">}</span>
</pre></div>
</div>
</div></blockquote>
<p id="index-4">The returned ufunc object is a callable Python object. It should be
placed in a (module) dictionary under the same name as was used in the
name argument to the ufunc-creation routine. The following example is
adapted from the umath module</p>
<blockquote>
<div><div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span> <span class="n">PyUFuncGenericFunction</span> <span class="n">atan2_functions</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
                      <span class="n">PyUFunc_ff_f</span><span class="p">,</span> <span class="n">PyUFunc_dd_d</span><span class="p">,</span>
                      <span class="n">PyUFunc_gg_g</span><span class="p">,</span> <span class="n">PyUFunc_OO_O_method</span><span class="p">};</span>
<span class="k">static</span> <span class="kt">void</span><span class="o">*</span> <span class="n">atan2_data</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
                      <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">atan2f</span><span class="p">,(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span> <span class="n">atan2</span><span class="p">,</span>
                      <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">atan2l</span><span class="p">,(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="s">&quot;arctan2&quot;</span><span class="p">};</span>
<span class="k">static</span> <span class="kt">char</span> <span class="n">atan2_signatures</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
              <span class="n">NPY_FLOAT</span><span class="p">,</span> <span class="n">NPY_FLOAT</span><span class="p">,</span> <span class="n">NPY_FLOAT</span><span class="p">,</span>
              <span class="n">NPY_DOUBLE</span><span class="p">,</span> <span class="n">NPY_DOUBLE</span><span class="p">,</span> <span class="n">NPY_DOUBLE</span><span class="p">,</span>
              <span class="n">NPY_LONGDOUBLE</span><span class="p">,</span> <span class="n">NPY_LONGDOUBLE</span><span class="p">,</span> <span class="n">NPY_LONGDOUBLE</span>
              <span class="n">NPY_OBJECT</span><span class="p">,</span> <span class="n">NPY_OBJECT</span><span class="p">,</span> <span class="n">NPY_OBJECT</span><span class="p">};</span>
<span class="p">...</span>
<span class="cm">/* in the module initialization code */</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">f</span><span class="p">,</span> <span class="o">*</span><span class="n">dict</span><span class="p">,</span> <span class="o">*</span><span class="n">module</span><span class="p">;</span>
<span class="p">...</span>
<span class="n">dict</span> <span class="o">=</span> <span class="n">PyModule_GetDict</span><span class="p">(</span><span class="n">module</span><span class="p">);</span>
<span class="p">...</span>
<span class="n">f</span> <span class="o">=</span> <span class="n">PyUFunc_FromFuncAndData</span><span class="p">(</span><span class="n">atan2_functions</span><span class="p">,</span>
    <span class="n">atan2_data</span><span class="p">,</span> <span class="n">atan2_signatures</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span>
    <span class="n">PyUFunc_None</span><span class="p">,</span> <span class="s">&quot;arctan2&quot;</span><span class="p">,</span>
    <span class="s">&quot;a safe and correct arctan(x1/x2)&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">PyDict_SetItemString</span><span class="p">(</span><span class="n">dict</span><span class="p">,</span> <span class="s">&quot;arctan2&quot;</span><span class="p">,</span> <span class="n">f</span><span class="p">);</span>
<span class="n">Py_DECREF</span><span class="p">(</span><span class="n">f</span><span class="p">);</span>
<span class="p">...</span>
</pre></div>
</div>
</div></blockquote>
</div>
</div>


          </div>
        </div>
          </div>
        </div>
      </div>
    </div>

    <div class="container container-navbar-bottom">
      <div class="spc-navbar">
        
      </div>
    </div>
    <div class="container">
    <div class="footer">
    <div class="row-fluid">
    <ul class="inline pull-left">
      <li>
        &copy; Copyright 2008-2019, The SciPy community.
      </li>
      <li>
      Last updated on Feb 20, 2020.
      </li>
      <li>
      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 2.4.2.
      </li>
    </ul>
    </div>
    </div>
    </div>
  </body>
</html>